home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / lock.c < prev    next >
C/C++ Source or Header  |  1993-01-05  |  20KB  |  802 lines

  1. /*    SCCS Id: @(#)lock.c    3.1    92/09/02
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6.  
  7. #define CONTAINER_BITS 0    /* box options not [yet?] implemented */
  8.  
  9. STATIC_PTR int NDECL(picklock);
  10. STATIC_PTR int NDECL(forcelock);
  11.  
  12. STATIC_VAR struct xlock_s {
  13.     int    door_or_box, picktyp;
  14.     struct rm  *door;
  15.     struct obj *box;
  16.     int chance, usedtime;
  17. } NEARDATA xlock;
  18.  
  19. #ifdef OVLB
  20.  
  21. static boolean FDECL(obstructed,(int,int));
  22. static void FDECL(chest_shatter_msg, (struct obj *));
  23.  
  24. boolean
  25. picking_at(x, y)
  26. int x, y;
  27. {
  28.     return((occupation == picklock) && 
  29.            xlock.door_or_box && (xlock.door == &levl[x][y])); 
  30. }
  31.  
  32. STATIC_PTR
  33. int
  34. picklock()    /* try to open/close a lock */
  35. {
  36.  
  37.     if(!xlock.door_or_box) {    /* box */
  38.  
  39.         if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
  40.         return((xlock.usedtime = 0));        /* you or it moved */
  41.         }
  42.     } else {        /* door */
  43.         if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
  44.         return((xlock.usedtime = 0));        /* you moved */
  45.         }
  46.         switch (xlock.door->doormask) {
  47.         case D_NODOOR:
  48.             pline("This doorway has no door.");
  49.             return((xlock.usedtime = 0));
  50.         case D_ISOPEN:
  51.             pline("Picking the lock of an open door is pointless.");
  52.             return((xlock.usedtime = 0));
  53.         case D_BROKEN:
  54.             pline("This door is broken.");
  55.             return((xlock.usedtime = 0));
  56.         }
  57.     }
  58.  
  59.     if(xlock.usedtime++ >= 50
  60. #ifdef POLYSELF
  61.        || nohands(uasmon)
  62. #endif
  63.        ) {
  64.         You("give up your attempt to %s the lock.",
  65.           (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
  66.            !xlock.box->olocked) ? "lock" :
  67.           ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  68.  
  69.         exercise(A_DEX, TRUE);    /* even if you don't succeed */
  70.         return((xlock.usedtime = 0));
  71.     }
  72.  
  73.     if(rn2(100) > xlock.chance) return(1);        /* still busy */
  74.  
  75.     if(xlock.door_or_box) {
  76.         You("succeed in %sing the lock.",
  77.           !(xlock.door->doormask & D_LOCKED) ? "lock" :
  78.           ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  79.         if(xlock.door->doormask & D_TRAPPED) {
  80.             b_trapped("door");
  81.             xlock.door->doormask = D_NODOOR;
  82.             unblock_point(u.ux+u.dx, u.uy+u.dy);
  83.             newsym(u.ux+u.dx, u.uy+u.dy);
  84.         } else if(xlock.door->doormask == D_LOCKED)
  85.         xlock.door->doormask = D_CLOSED;
  86.         else xlock.door->doormask = D_LOCKED;
  87.     } else {
  88.         You("succeed in %sing the lock.",
  89.           (!xlock.box->olocked) ? "lock" :
  90.           (xlock.picktyp == LOCK_PICK) ? "pick" : "open" );
  91.         xlock.box->olocked = !xlock.box->olocked;
  92.         if(xlock.box->otrapped)    
  93.         (void) chest_trap(xlock.box, FINGER, FALSE);
  94.     }
  95.     exercise(A_DEX, TRUE);
  96.     return((xlock.usedtime = 0));
  97. }
  98.  
  99. STATIC_PTR
  100. int
  101. forcelock()    /* try to force a locked chest */
  102. {
  103.  
  104.     register struct obj *otmp, *otmp2;
  105.  
  106.     if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
  107.         return((xlock.usedtime = 0));        /* you or it moved */
  108.  
  109.     if(xlock.usedtime++ >= 50 || !uwep
  110. #ifdef POLYSELF
  111.        || nohands(uasmon)
  112. #endif
  113.        ) {
  114.         You("give up your attempt to force the lock.");
  115.         if(xlock.usedtime >= 50)        /* you made the effort */
  116.           exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  117.         return((xlock.usedtime = 0));
  118.     }
  119.  
  120.     if(xlock.picktyp) {    /* blade */
  121.  
  122.         if(rn2(1000-(int)uwep->spe) > (992-(int)uwep->oeroded*10) && 
  123.            !uwep->cursed) {
  124.         /* for a +0 weapon, probability that it survives an unsuccessful
  125.          * attempt to force the lock is (.992)^50 = .67
  126.          */
  127.         pline("%sour %s broke!",
  128.               (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep));
  129.         useup(uwep);
  130.         You("give up your attempt to force the lock.");
  131.         exercise(A_DEX, TRUE);
  132.         return((xlock.usedtime = 0));
  133.         }
  134.     } else            /* blunt */
  135.         wake_nearby();    /* due to hammering on the container */
  136.  
  137.     if(rn2(100) > xlock.chance) return(1);        /* still busy */
  138.  
  139.     You("succeed in forcing the lock.");
  140.     xlock.box->olocked = 0;
  141.     xlock.box->obroken = 1;
  142.     if(!xlock.picktyp && !rn2(3)) {
  143.         register struct monst *shkp;
  144.         long loss = 0L;
  145.  
  146. #ifdef GCC_WARN
  147.         shkp = (struct monst *) 0;
  148. #endif
  149.  
  150.         if(*u.ushops) shkp = shop_keeper(*u.ushops);
  151.  
  152.         pline("In fact, you've totally destroyed %s.",
  153.           the(xname(xlock.box)));
  154.  
  155.         /* Put the contents on ground at the hero's feet. */
  156.         for (otmp = xlock.box->cobj; otmp; otmp = otmp2) {
  157.         otmp2 = otmp->nobj;
  158.         if(!rn2(3) || otmp->oclass == POTION_CLASS) {
  159.             chest_shatter_msg(otmp);
  160.             if(*u.ushops && costly_spot(u.ux, u.uy))
  161.                 loss += stolen_value(otmp, u.ux, u.uy,
  162.                          (boolean)shkp->mpeaceful, TRUE);
  163.             if (otmp->quan == 1L) {
  164.             obfree(otmp, (struct obj *) 0);
  165.             continue;
  166.             }
  167.             useup(otmp);
  168.         }
  169.         place_object(otmp,u.ux,u.uy);
  170.         otmp->nobj = fobj;
  171.         fobj = otmp;
  172.         stackobj(otmp);
  173.         }
  174.         xlock.box->cobj = (struct obj *) 0;    /* no contents */
  175.         if(*u.ushops && costly_spot(u.ux, u.uy))
  176.         loss += stolen_value(otmp, u.ux, u.uy,
  177.                          (boolean)shkp->mpeaceful, TRUE);
  178.         if(loss) You("owe %ld zorkmids for objects destroyed.", loss);
  179.         delobj(xlock.box);
  180.     }
  181.     exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  182.     return((xlock.usedtime = 0));
  183. }
  184.  
  185. #endif /* OVLB */
  186. #ifdef OVL0
  187.  
  188. void
  189. reset_pick() { xlock.usedtime = 0; }
  190.  
  191. #endif /* OVL0 */
  192. #ifdef OVLB
  193.  
  194. int
  195. pick_lock(pick) /* pick a lock with a given object */
  196.     register struct    obj    *pick;
  197. {
  198.     register int x, y, picktyp, c, ch;
  199.     register struct rm    *door;
  200.     register struct obj    *otmp;
  201.     char qbuf[QBUFSZ];
  202.  
  203. #ifdef GCC_WARN
  204.     ch = 0;        /* GCC myopia */
  205. #endif
  206.     picktyp = pick->otyp;
  207.     if(xlock.usedtime && picktyp == xlock.picktyp) {
  208.  
  209.         You("resume your attempt to %s the lock.",
  210.           (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
  211.            !xlock.box->olocked) ? "lock" :
  212.           ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
  213.  
  214.         set_occupation(picklock,
  215.                (picktyp == LOCK_PICK) ? "picking the lock" :
  216.                             "opening the lock",  0);
  217.         return(1);
  218.     }
  219.  
  220. #ifdef POLYSELF
  221.     if(nohands(uasmon)) {
  222.         You("can't hold a %s - you have no hands!", xname(pick));
  223.         return(0);
  224.     }
  225. #endif
  226.     if((picktyp != LOCK_PICK &&
  227. #ifdef TOURIST
  228.         picktyp != CREDIT_CARD &&
  229. #endif
  230.         picktyp != SKELETON_KEY)) {
  231.         impossible("picking lock with object %d?", picktyp);
  232.         return(0);
  233.     }
  234.     if(!getdir(NULL)) return(0);
  235.  
  236.     x = u.ux + u.dx;
  237.     y = u.uy + u.dy;
  238.     if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */
  239.         c = 'n';            /* in case there are no boxes here */
  240.         for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  241.         if (Is_box(otmp)) {
  242.             const char *verb;
  243.             boolean it = 0;
  244. #if CONTAINER_BITS
  245.             if (!otmp->oclosed) {    /* it's open */
  246.             pline("There is %s here.", doname(otmp));
  247.             continue;
  248.             }
  249.             if (!otmp->lknown) verb = "work";
  250.             else
  251. #endif
  252.              if (otmp->obroken) verb = "fix";
  253.             else if (!otmp->olocked) verb = "lock", it = 1;
  254.             else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
  255.             else verb = "pick";
  256.             Sprintf(qbuf, "There is %s here, %s %s?",
  257.                 doname(otmp), verb, it ? "it" : "its lock");
  258.  
  259.             c = ynq(qbuf);
  260.             if(c == 'q') return(0);
  261.             if(c == 'n') continue;
  262.  
  263. #if CONTAINER_BITS
  264.             otmp->lknown = 1;
  265. #endif
  266.             if (otmp->obroken) {
  267.             You("can't fix its broken lock with %s.", doname(pick));
  268.             return 0;
  269.             }
  270. #ifdef TOURIST
  271.             else if (picktyp == CREDIT_CARD && !otmp->olocked) {
  272.             /* credit cards are only good for unlocking */
  273.             You("can't do that with %s.", doname(pick));
  274.             return 0;
  275.             }
  276. #endif
  277.             switch(picktyp) {
  278. #ifdef TOURIST
  279.             case CREDIT_CARD:
  280.                 ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  281.                 break;
  282. #endif
  283.             case LOCK_PICK:
  284.                 ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R'));
  285.                 break;
  286.             case SKELETON_KEY:
  287.                 ch = 75 + ACURR(A_DEX);
  288.                 break;
  289.             default:    ch = 0;
  290.             }
  291.             if(otmp->cursed) ch /= 2;
  292.  
  293.             xlock.door_or_box = 0;
  294.             xlock.picktyp = picktyp;
  295.             xlock.box = otmp;
  296.             break;
  297.         }
  298.         if(c != 'y')
  299.         return(0);        /* decided against all boxes */
  300.     } else {            /* pick the lock in a door */
  301.         struct monst *mtmp;
  302.  
  303.         door = &levl[x][y];
  304.         if ((mtmp = m_at(x, y)) && canseemon(mtmp)
  305.             && mtmp->m_ap_type != M_AP_FURNITURE
  306.             && mtmp->m_ap_type != M_AP_OBJECT) {
  307. #ifdef TOURIST
  308.         if (picktyp == CREDIT_CARD &&
  309.             (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
  310.             verbalize("No checks, no credit, no problem.");
  311.         else
  312. #endif
  313.             pline("I don't think %s would appreciate that.", mon_nam(mtmp));
  314.         return(0);
  315.         }
  316.         if(!IS_DOOR(door->typ)) {
  317.         if (is_drawbridge_wall(x,y) >= 0)
  318.             You("%s no lock on the drawbridge.",
  319.                 Blind ? "feel" : "see");
  320.         else
  321.             You("%s no door there.",
  322.                 Blind ? "feel" : "see");
  323.         return(0);
  324.         }
  325.         switch (door->doormask) {
  326.         case D_NODOOR:
  327.             pline("This doorway has no door.");
  328.             return(0);
  329.         case D_ISOPEN:
  330.             pline("Picking the lock of an open door is pointless.");
  331.             return(0);
  332.         case D_BROKEN:
  333.             pline("This door is broken.");
  334.             return(0);
  335.         default:
  336. #ifdef TOURIST
  337.             /* credit cards are only good for unlocking */
  338.             if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
  339.             You("can't lock a door with a credit card.");
  340.             return(0);
  341.             }
  342. #endif
  343.  
  344.             Sprintf(qbuf,"%sock it?",
  345.             (door->doormask & D_LOCKED) ? "Unl" : "L" );
  346.  
  347.             c = yn(qbuf);
  348.             if(c == 'n') return(0);
  349.  
  350.             switch(picktyp) {
  351. #ifdef TOURIST
  352.             case CREDIT_CARD:
  353.                 ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  354.                 break;
  355. #endif
  356.             case LOCK_PICK:
  357.                 ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R'));
  358.                 break;
  359.             case SKELETON_KEY:
  360.                 ch = 70 + ACURR(A_DEX);
  361.                 break;
  362.             default:    ch = 0;
  363.             }
  364.             xlock.door_or_box = 1;
  365.             xlock.door = door;
  366.         }
  367.     }
  368.     flags.move = 0;
  369.     xlock.chance = ch;
  370.     xlock.picktyp = picktyp;
  371.     xlock.usedtime = 0;
  372.     set_occupation(picklock,
  373.                (picktyp == LOCK_PICK) ? "picking the lock" :
  374.                         "opening the lock",  0);
  375.     return(1);
  376. }
  377.  
  378. int
  379. doforce()        /* try to force a chest with your weapon */
  380. {
  381.     register struct obj *otmp;
  382.     register int c, picktyp;
  383.     char qbuf[QBUFSZ];
  384.  
  385.     if(!uwep ||    /* proper type test */
  386.        (uwep->oclass != WEAPON_CLASS && uwep->oclass != ROCK_CLASS &&
  387.                         uwep->otyp != PICK_AXE) ||
  388.        (uwep->otyp < BOOMERANG) ||
  389.        (uwep->otyp > AKLYS && uwep->oclass != ROCK_CLASS &&
  390.                         uwep->otyp != PICK_AXE)
  391. #ifdef KOPS
  392.        || uwep->otyp == RUBBER_HOSE
  393. #endif
  394.       ) {
  395.         You("can't force anything without a %sweapon.",
  396.           (uwep) ? "proper " : "");
  397.         return(0);
  398.     }
  399.  
  400.     picktyp = is_blade(uwep);
  401.     if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {
  402.         You("resume your attempt to force the lock.");
  403.         set_occupation(forcelock, "forcing the lock", 0);
  404.         return(1);
  405.     }
  406.  
  407.     /* A lock is made only for the honest man, the thief will break it. */
  408.     xlock.box = (struct obj *)0;
  409.     for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
  410.         if(Is_box(otmp)) {
  411. #if CONTAINER_BITS
  412.         if (!otmp->oclosed) {    /* it's open */
  413.             pline("There is %s here.", doname(otmp));
  414.             continue;
  415.         }
  416.         if (otmp->obroken || (otmp->lknown && !otmp->olocked)) {
  417. #else
  418.         if (otmp->obroken || !otmp->olocked) {
  419. #endif
  420.             pline("There is %s here, but its lock is already %s.",
  421.               doname(otmp), otmp->obroken ? "broken" : "unlocked");
  422.             continue;
  423.         }
  424.         Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp));
  425.  
  426.         c = ynq(qbuf);
  427.         if(c == 'q') return(0);
  428.         if(c == 'n') continue;
  429.  
  430. #if CONTAINER_BITS
  431.         if (!otmp->olocked) {    /* lock-status wasn't known */
  432.             pline("Well what'd'ya know?  It's already unlocked.");
  433.             otmp->lknown = 1;
  434.             return 0;
  435.         }
  436. #endif
  437.         if(picktyp)
  438.             You("force your %s into a crack and pry.", xname(uwep));
  439.         else
  440.             You("start bashing it with your %s.", xname(uwep));
  441.         xlock.box = otmp;
  442.         xlock.chance = objects[otmp->otyp].oc_wldam * 2;
  443.         xlock.picktyp = picktyp;
  444.         xlock.usedtime = 0;
  445.         break;
  446.         }
  447.  
  448.     if(xlock.box)    set_occupation(forcelock, "forcing the lock", 0);
  449.     else        You("decide not to force the issue.");
  450.     return(1);
  451. }
  452.  
  453. int
  454. doopen()        /* try to open a door */
  455. {
  456.     register int x, y;
  457.     register struct rm *door;
  458.     struct monst *mtmp;
  459.  
  460.     if (u.utrap && u.utraptype == TT_PIT) {
  461.         You("can't reach over the edge of the pit.");
  462.         return 0;
  463.     }
  464.  
  465.     if(!getdir(NULL)) return(0);
  466.  
  467.     x = u.ux + u.dx;
  468.     y = u.uy + u.dy;
  469.     if((x == u.ux) && (y == u.uy)) return(0);
  470.  
  471.     if ((mtmp = m_at(x,y))                &&
  472.         mtmp->m_ap_type == M_AP_FURNITURE    &&
  473.         (mtmp->mappearance == S_hcdoor ||
  474.             mtmp->mappearance == S_vcdoor)    &&
  475.         !Protection_from_shape_changers)     {
  476.  
  477.         stumble_onto_mimic(mtmp);
  478.         return(1);
  479.     }
  480.  
  481.     door = &levl[x][y];
  482.  
  483.     if(!IS_DOOR(door->typ)) {
  484.         if (is_db_wall(x,y)) {
  485.             pline("There is no obvious way to open the drawbridge.");
  486.             return(0);
  487.         }
  488.         You("%s no door there.",
  489.                 Blind ? "feel" : "see");
  490.         return(0);
  491.     }
  492.  
  493.     if(!(door->doormask & D_CLOSED)) {
  494.       switch(door->doormask) {
  495.          case D_BROKEN: pline("This door is broken."); break;
  496.          case D_NODOOR: pline("This doorway has no door."); break;
  497.          case D_ISOPEN: pline("This door is already open."); break;
  498.          default:        pline("This door is locked."); break;
  499.       }
  500.       return(0);
  501.     }
  502.  
  503. #ifdef POLYSELF
  504.     if(verysmall(uasmon)) {
  505.         pline("You're too small to pull the door open.");
  506.         return(0);
  507.     }
  508. #endif
  509.     /* door is known to be CLOSED */
  510.     if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  511.         pline("The door opens.");
  512.         if(door->doormask & D_TRAPPED) {
  513.         b_trapped("door");
  514.         door->doormask = D_NODOOR;
  515.         } else
  516.         door->doormask = D_ISOPEN;
  517.         if (Blind)
  518.         feel_location(x,y);    /* the hero knows she opened it  */
  519.         else
  520.         newsym(x,y);
  521.         unblock_point(x,y);        /* vision: new see through there */
  522.     } else {
  523.         exercise(A_STR, TRUE);
  524.         pline("The door resists!");
  525.     }
  526.  
  527.     return(1);
  528. }
  529.  
  530. static
  531. boolean
  532. obstructed(x,y)
  533. register int x, y;
  534. {
  535.     register struct monst *mtmp = m_at(x, y);
  536.  
  537.     if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
  538.         if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
  539.         pline("%s stands in the way!", Blind ?
  540.             "Some creature" : Monnam(mtmp));
  541.         return(TRUE);
  542.     }
  543.     if (OBJ_AT(x, y)) {
  544. objhere:    pline("Something's in the way.");
  545.         return(TRUE);
  546.     }
  547.     return(FALSE);
  548. }
  549.  
  550. int
  551. doclose()        /* try to close a door */
  552. {
  553.     register int x, y;
  554.     register struct rm *door;
  555.     struct monst *mtmp;
  556.  
  557.     if (u.utrap && u.utraptype == TT_PIT) {
  558.         You("can't reach over the edge of the pit.");
  559.         return 0;
  560.     }
  561.  
  562.     if(!getdir(NULL)) return(0);
  563.  
  564.     x = u.ux + u.dx;
  565.     y = u.uy + u.dy;
  566.     if((x == u.ux) && (y == u.uy)) {
  567.         You("are in the way!");
  568.         return(1);
  569.     }
  570.  
  571.     if ((mtmp = m_at(x,y))                &&
  572.         mtmp->m_ap_type == M_AP_FURNITURE    && 
  573.         (mtmp->mappearance == S_hcdoor ||
  574.             mtmp->mappearance == S_vcdoor)    &&
  575.         !Protection_from_shape_changers)     {
  576.  
  577.         stumble_onto_mimic(mtmp);
  578.         return(1);
  579.     }
  580.  
  581.     door = &levl[x][y];
  582.  
  583.     if(!IS_DOOR(door->typ)) {
  584.         if (door->typ == DRAWBRIDGE_DOWN)
  585.             pline("There is no obvious way to close the drawbridge.");
  586.         else
  587.             You("%s no door there.",
  588.                 Blind ? "feel" : "see");
  589.         return(0);
  590.     }
  591.  
  592.     if(door->doormask == D_NODOOR) {
  593.         pline("This doorway has no door.");
  594.         return(0);
  595.     }
  596.  
  597.     if(obstructed(x, y)) return(0);
  598.  
  599.     if(door->doormask == D_BROKEN) {
  600.         pline("This door is broken.");
  601.         return(0);
  602.     }
  603.  
  604.     if(door->doormask & (D_CLOSED | D_LOCKED)) {
  605.         pline("This door is already closed.");
  606.         return(0);
  607.     }
  608.  
  609.     if(door->doormask == D_ISOPEN) {
  610. #ifdef POLYSELF
  611.         if(verysmall(uasmon)) {
  612.          pline("You're too small to push the door closed.");
  613.          return(0);
  614.          }
  615. #endif
  616.         if (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  617.         pline("The door closes.");
  618.         door->doormask = D_CLOSED;
  619.         if (Blind)
  620.             feel_location(x,y);    /* the hero knows she closed it */
  621.         else
  622.             newsym(x,y);
  623.         block_point(x,y);    /* vision:  no longer see there */
  624.         }
  625.         else {
  626.             exercise(A_STR, TRUE);
  627.             pline("The door resists!");
  628.         }
  629.     }
  630.  
  631.     return(1);
  632. }
  633.  
  634. boolean            /* box obj was hit with spell effect otmp */
  635. boxlock(obj, otmp)    /* returns true if something happened */
  636. register struct obj *obj, *otmp;    /* obj *is* a box */
  637. {
  638.     register boolean res = 0;
  639.  
  640.     switch(otmp->otyp) {
  641.     case WAN_LOCKING:
  642.     case SPE_WIZARD_LOCK:
  643.         if (!obj->olocked) {    /* lock it; fix if broken */
  644.         pline("Klunk!");
  645. #if CONTAINER_BITS
  646.         obj->lknown = 0;
  647.         obj->oclosed = 1;
  648. #endif
  649.         obj->olocked = 1;
  650.         obj->obroken = 0;
  651.         res = 1;
  652.         } /* else already closed and locked */
  653.         break;
  654.     case WAN_OPENING:
  655.     case SPE_KNOCK:
  656.         if (obj->olocked) {        /* unlock; couldn't be broken */
  657.         pline("Klick!");
  658. #if CONTAINER_BITS
  659.         obj->lknown = 0;
  660. #endif
  661.         obj->olocked = 0;
  662.         res = 1;
  663.         } else            /* silently fix if broken */
  664.         obj->obroken = 0;
  665. #if CONTAINER_BITS
  666.         obj->oclosed = 0;        /* now open, unconditionally */
  667. #endif
  668.         break;
  669.     }
  670.     return res;
  671. }
  672.  
  673. boolean            /* Door/secret door was hit with spell effect otmp */
  674. doorlock(otmp,x,y)    /* returns true if something happened */
  675. register struct obj *otmp;
  676. int x, y;
  677. {
  678.     register struct rm *door = &levl[x][y];
  679.     boolean res = 1;
  680.     const char *msg = NULL;
  681.  
  682.     if (door->typ == SDOOR) {
  683.         if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
  684.         door->typ = DOOR;
  685.         door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  686.         if (cansee(x,y)) pline("A section of the wall opens up!");
  687.         newsym(x,y);
  688.         return(1);
  689.         } else
  690.         return(0);
  691.     }
  692.  
  693.     switch(otmp->otyp) {
  694.     case WAN_LOCKING:
  695.     case SPE_WIZARD_LOCK:
  696.         if (obstructed(x,y)) return 0;
  697.         switch (door->doormask & ~D_TRAPPED) {
  698.         case D_CLOSED:
  699.         msg = "The door locks!";
  700.         break;
  701.         case D_ISOPEN:
  702.         msg = "The door swings shut, and locks!";
  703.         break;
  704.         case D_BROKEN:
  705.         msg = "The broken door reassembles and locks!";
  706.         break;
  707.         case D_NODOOR:
  708.         msg =
  709.         "A cloud of dust springs up and assembles itself into a door!";
  710.         break;
  711.         default:
  712.         res = 0;
  713.         break;
  714.         }
  715.         block_point(x, y);
  716.         door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
  717.         newsym(x,y);
  718.         break;
  719.     case WAN_OPENING:
  720.     case SPE_KNOCK:
  721.         if (door->doormask & D_LOCKED) {
  722.         msg = "The door unlocks!";
  723.         door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  724.         } else res = 0;
  725.         break;
  726.     case WAN_STRIKING:
  727.     case SPE_FORCE_BOLT:
  728.         if (door->doormask & (D_LOCKED | D_CLOSED)) {
  729.         if (door->doormask & D_TRAPPED) {
  730.             if (MON_AT(x, y))
  731.             (void) mb_trapped(m_at(x,y));
  732.             else if (flags.verbose) {
  733.             if (cansee(x,y))
  734.                 pline("KABOOM!!  You see a door explode.");
  735.             else if (flags.soundok)
  736.                 You("hear a distant explosion.");
  737.             }
  738.             door->doormask = D_NODOOR;
  739.             unblock_point(x,y);
  740.             newsym(x,y);
  741.             break;
  742.         }
  743.         door->doormask = D_BROKEN;
  744.         if (flags.verbose) {
  745.             if (cansee(x,y))
  746.             pline("The door crashes open!");
  747.             else if (flags.soundok)
  748.             You("hear a crashing sound.");
  749.         }
  750.         unblock_point(x,y);
  751.         newsym(x,y);
  752.         } else res = 0;
  753.         break;
  754.     default: impossible("magic (%d) attempted on door.", otmp->otyp);
  755.         break;
  756.     }
  757.     if (msg && cansee(x,y)) pline(msg);
  758.     return res;
  759. }
  760.  
  761. static void
  762. chest_shatter_msg(otmp)
  763. struct obj *otmp;
  764. {
  765.     const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The";
  766.     char *thing;
  767.     long save_Blinded;
  768.  
  769.     if (otmp->oclass == POTION_CLASS) {
  770.         You("%s a flask shatter!", Blind ? "hear" : "see");
  771.         potionbreathe(otmp);
  772.         return;
  773.     }
  774.     /* We have functions for distant and singular names, but not one */
  775.     /* which does _both_... */
  776.     save_Blinded = Blinded;
  777.     Blinded = 1;
  778.     thing = singular(otmp, xname);
  779.     Blinded = save_Blinded;
  780.     switch (objects[otmp->otyp].oc_material) {
  781.     case PAPER:    disposition = "is torn to shreds";
  782.         break;
  783.     case WAX:    disposition = "is crushed";
  784.         break;
  785.     case VEGGY:    disposition = "is pulped";
  786.         break;
  787.     case FLESH:    disposition = "is mashed";
  788.         break;
  789.     case GLASS:    disposition = "shatters";
  790.         break;
  791.     case WOOD:    disposition = "splinters to fragments";
  792.         break;
  793.     default:    disposition = "is destroyed";
  794.         break;
  795.     }
  796.     pline("%s %s %s!", article, thing, disposition);
  797. }
  798.  
  799. #endif /* OVLB */
  800.  
  801. /*lock.c*/
  802.